package edu.whu.notepal.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import edu.whu.notepal.common.CustomException;
import edu.whu.notepal.dto.NoteDTO;
import edu.whu.notepal.pojo.Group;
import edu.whu.notepal.pojo.Note;
import edu.whu.notepal.pojo.Subscriber;
import edu.whu.notepal.pojo.User;
import edu.whu.notepal.service.GroupService;
import edu.whu.notepal.service.NoteService;
import edu.whu.notepal.mapper.NoteMapper;
import edu.whu.notepal.service.SubscriberService;
import edu.whu.notepal.service.UserService;
import edu.whu.notepal.utils.UserHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.LinkedList;
import java.util.List;

/**
* @author 陈磊
* @description 针对表【t_note】的数据库操作Service实现
* @createDate 2022-11-17 09:16:39
*/
@Service
public class NoteServiceImpl extends ServiceImpl<NoteMapper, Note>
    implements NoteService{

    @Resource
    UserService userService;

    @Resource
    GroupService groupService;

    @Resource
    SubscriberService subscriberService;

    @Override
    public List<Note> getSimpleInfo(Long startIndex, Long size, LambdaQueryWrapper<Note> wrapper,boolean visibleOnly) {
        wrapper.orderByDesc(Note::getUpdateTime);
        wrapper.select(Note::getId,Note::getTitle,Note::getPublisherId,Note::getPrivateChat);
        if(visibleOnly){
            wrapper.eq(Note::getVisible,true);
        }
        wrapper.last("limit "+startIndex+","+size);
        List<Note> list =  list(wrapper);
        if(list.size()==0){
           throw new CustomException("暂时没有更多数据了");
        }
        return list;
    }

    @Override
    public void changeVisible(Long noteId,Boolean visible) {
        LambdaUpdateWrapper<Note> noteWrapper = new LambdaUpdateWrapper<>();
        noteWrapper.set(Note::getVisible,visible);
        noteWrapper.eq(Note::getId,noteId);
        update(noteWrapper);
    }

    @Override
    public List<Note> getByUserId(Long userId, Long startIndex, Long size){
        LambdaQueryWrapper<Note> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Note::getPublisherId,userId);
        List<Note> list = getSimpleInfo(startIndex, size, wrapper,false);
        return list;
    }

    @Override
    public List<NoteDTO> getNotesByColumnId(Long columnId, Long startIndex, Long size) {
        LambdaQueryWrapper<Note> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Note::getColumnId,columnId);
        wrapper.gt(Note::getDeadline, LocalDateTime.now());
        List<Note> simpleInfo = getSimpleInfo(startIndex, size, wrapper,true);
        LinkedList<NoteDTO> list = new LinkedList<>();
        simpleInfo.forEach(
                note->{
                    LambdaQueryWrapper<User> userWrapper = new LambdaQueryWrapper<>();
                    userWrapper.eq(User::getId,note.getPublisherId());
                    userWrapper.select(User::getIcon,User::getName);
                    User user = userService.getOne(userWrapper);
                    NoteDTO dto = BeanUtil.copyProperties(note, NoteDTO.class);
                    dto.setIcon(user.getIcon());
                    dto.setUsername(user.getName());
                    list.add(dto);
                }
        );
        return list;
    }


    @Override
    public NoteDTO getDetailsById(Long id) {
        Note note = getById(id);
        NoteDTO noteDTO = BeanUtil.copyProperties(note, NoteDTO.class);
        if(note.getPrivateChat()){
            noteDTO.setExceptedNumbers(1);
            noteDTO.setActualNumbers(note.getVisible()?1:0);
        }else {
            LambdaQueryWrapper<Group> groupWrapper = new LambdaQueryWrapper<>();
            groupWrapper.select(Group::getExceptedNumbers, Group::getActualNumbers);
            groupWrapper.eq(Group::getNoteId,id);
            Group group = groupService.getOne(groupWrapper);
            noteDTO.setExceptedNumbers(group.getExceptedNumbers());
            noteDTO.setActualNumbers(group.getActualNumbers());
        }
        return noteDTO;
    }

    @Transactional(rollbackFor=Exception.class)
    @Override
    public void saveWithGroup(NoteDTO noteDTO) {
        save(noteDTO);
        Group group = new Group();
        group.setNoteId(noteDTO.getId());
        group.setName(noteDTO.getTitle());
        group.setExceptedNumbers(noteDTO.getExceptedNumbers());
        group.setActualNumbers(0);
        Long publisherId = UserHolder.getUser().getId();
        group.setPublisherId(publisherId);
        groupService.save(group);
        Subscriber subscriber = new Subscriber();
        subscriber.setSubscriberId(publisherId);
        subscriber.setGroupId(noteDTO.getId());
        subscriberService.save(subscriber);
    }

    @Override
    public Long getPublisher(Long noteId) {
        LambdaQueryWrapper<Note> noteWapper = new LambdaQueryWrapper<>();
        noteWapper.select(Note::getPublisherId);
        noteWapper.eq(Note::getId,noteId);
        return getOne(noteWapper).getPublisherId();
    }

}